package com.siao.component
{
	import com.siao.component.scroller.ScrollBar;
	import com.siao.component.scroller.ScrollList;
	import com.siao.data.ArrayList;
	import com.siao.display.Align;
	import com.siao.display.LayoutElement;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	[Event(name="select", type="flash.events.Event")]
	
	[Event(name="open", type="flash.events.Event")]
	
	[Event(name="close", type="flash.events.Event")]
	
	/**
	 * 下拉菜单组件
	 * @author SiaoLeon
	 */
	public class ComboBox extends LayoutElement implements ISelector
	{
		// -------------------------------------------------------------------------------------------------------- 静态常量
		
		// -------------------------------------------------------------------------------------------------------- 静态变量
		
		// -------------------------------------------------------------------------------------------------------- 静态方法
		
		// -------------------------------------------------------------------------------------------------------- 静态函数
		
		// -------------------------------------------------------------------------------------------------------- 属性
		
		private var _selected:*;
		
		/**
		 * 选中的项目
		 * @return
		 */
		public function get selected():*
		{
			return this._selected;
		}
		
		public function set selected(value:*):void
		{
			this._selected = value;
			this.dispatchEvent(new Event(Event.SELECT));
		}
		
		/**
		 * 强制向下拉开，开启该选项，将指定下拉列表出现在菜单下方。
		 * @default false
		 */
		public var forceBottom:Boolean;
		
		private var _scrollEasing:Boolean;
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.scrollEasing
		 */
		public function get scrollEasing():Boolean
		{
			return this.itemList.scrollEasing;
		}
		
		public function set scrollEasing(value:Boolean):void
		{
			this.itemList.scrollEasing = value;
		}
		
		private var _scrollDrag:Boolean;
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.scrollDrag
		 */
		public function get scrollDrag():Boolean
		{
			return this.itemList.scrollDrag;
		}
		
		public function set scrollDrag(value:Boolean):void
		{
			this.itemList.scrollDrag = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.scrollWheel
		 */
		public function get scrollWheel():Boolean
		{
			return this.itemList.scrollWheel;
		}
		
		public function set scrollWheel(value:Boolean):void
		{
			this.itemList.scrollWheel = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.rowSpacing
		 */
		public function get rowSpacing():Number
		{
			return this.itemList.rowSpacing;
		}
		
		public function set rowSpacing(value:Number):void
		{
			this.itemList.rowSpacing = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.contentAlignH
		 */
		public function get contentAlignH():uint
		{
			return this.itemList.contentAlignH;
		}
		
		public function set contentAlignH(value:uint):void
		{
			this.itemList.contentAlignH = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.maskMargin
		 */
		public function set maskMargin(value:Number):void
		{
			this.itemList.maskMargin = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.maskMarginLeft
		 */
		public function get maskMarginLeft():Number
		{
			return this.itemList.maskMarginLeft;
		}
		
		public function set maskMarginLeft(value:Number):void
		{
			this.itemList.maskMarginLeft = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.maskMarginRight
		 */
		public function get maskMarginRight():Number
		{
			return this.itemList.maskMarginRight;
		}
		
		public function set maskMarginRight(value:Number):void
		{
			this.itemList.maskMarginRight = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.maskMarginTop
		 */
		public function get maskMarginTop():Number
		{
			return this.itemList.maskMarginTop;
		}
		
		public function set maskMarginTop(value:Number):void
		{
			this.itemList.maskMarginTop = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.maskMarginBottom
		 */
		public function get maskMarginBottom():Number
		{
			return this.itemList.maskMarginBottom;
		}
		
		public function set maskMarginBottom(value:Number):void
		{
			this.itemList.maskMarginBottom = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.vScrollBar
		 */
		public function get scrollBar():ScrollBar
		{
			return this.itemList.vScrollBar;
		}
		
		public function set scrollBar(value:ScrollBar):void
		{
			this.itemList.vScrollBar = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.itemClass
		 */
		public function get itemClass():Class
		{
			return this.itemList.itemClass;
		}
		
		public function set itemClass(value:Class):void
		{
			this.itemList.itemClass = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.data
		 */
		public function get data():ArrayList
		{
			return this.itemList.data;
		}
		
		public function set data(value:ArrayList):void
		{
			this.itemList.data = value;
		}
		
		private var _listWidth:Number;
		
		/**
		 * 列表宽度
		 * @return
		 */
		public function get listWidth():Number
		{
			return this.itemList.width;
		}
		
		public function set listWidth(value:Number):void
		{
			this._listWidth = this.itemList.width = value;
		}
		
		private var _listHeight:Number;
		
		/**
		 * 列表高度
		 * @return
		 */
		public function get listHeight():Number
		{
			return this.itemList.height;
		}
		
		public function set listHeight(value:Number):void
		{
			_listHeight = this.itemList.height = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.paddingLeft
		 */
		public function get listPaddingLeft():Number
		{
			return this.itemList.paddingLeft;
		}
		
		public function set listPaddingLeft(value:Number):void
		{
			this.itemList.paddingLeft = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.paddingRight
		 */
		public function get listPaddingRight():Number
		{
			return this.itemList.paddingRight;
		}
		
		public function set listPaddingRight(value:Number):void
		{
			this.itemList.paddingRight = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.paddingTop
		 */
		public function get listPaddingTop():Number
		{
			return this.itemList.paddingTop;
		}
		
		public function set listPaddingTop(value:Number):void
		{
			this.itemList.paddingTop = value;
		}
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.paddingBottom
		 */
		public function get listPaddingBottom():Number
		{
			return this.itemList.paddingBottom;
		}
		
		public function set listPaddingBottom(value:Number):void
		{
			this.itemList.paddingBottom = value;
		}
		
		private var _listContainer:DisplayObjectContainer;
		
		/**
		 * 列表弹出容器，若不设定将弹出在当前父级容器内
		 * @return
		 */
		public function get listContainer():DisplayObjectContainer
		{
			return this._listContainer;
		}
		
		public function set listContainer(value:DisplayObjectContainer):void
		{
			this._listContainer = value;
			
			this.init();
		}
		
		private var _listBackground:DisplayObject;
		
		/**
		 * 列表背景
		 * @return
		 */
		public function get listBackground():DisplayObject
		{
			return this._listBackground;
		}
		
		public function set listBackground(value:DisplayObject):void
		{
			if (this._listBackground != null && this.itemList.contains(this._listBackground))
			{
				this.itemList.removeChild(this._listBackground);
			}
			
			this._listBackground = value;
			this.itemList.addChildAt(this._listBackground, 0);
		}
		
		public var itemList:ScrollList = new ScrollList();
		
		// -------------------------------------------------------------------------------------------------------- 变量
		
		// -------------------------------------------------------------------------------------------------------- 构造
		
		/**
		 * 构造函数
		 * @param listContainer 列表弹出容器，若不设定将弹出在当前父级容器内
		 */
		public function ComboBox(listContainer:DisplayObjectContainer=null)
		{
			super();
			
			this._listContainer = listContainer;
			
			this.itemList.contentAlignV = Align.TOP;
			this.itemList.draw(0XFF0000, 0);
			
			this.draw(0X000000, 0);
		}
		
		// -------------------------------------------------------------------------------------------------------- 方法
		
		/**
		 * @copy com.siao.component.scroller.ScrollList.bind()
		 */
		public function bind(itemClass:Class, data:ArrayList):void
		{
			this.itemList.bind(itemClass, data);
			this.selected = this.itemList.selected;
		}
		
		/**
		 * 打开列表
		 */
		private function openList():void
		{
			var maxListWidth:Number = this.itemList.itemWidth + this.itemList.paddingLeft + this.itemList.paddingRight + this.itemList.maskMarginLeft + this.itemList.maskMarginRight;
			var maxListHeight:Number = (this.itemList.itemHeight + this.itemList.rowSpacing) * this.itemList.data.length - this.itemList.rowSpacing + this.itemList.paddingTop + this.itemList.paddingBottom + this.itemList.maskMarginTop + this.itemList.maskMarginBottom;
			var left:Number = this.localToGlobal(new Point(0, 0)).x;
			var right:Number = this.stage.stageWidth - this.localToGlobal(new Point(0, this.width)).x;
			var top:Number = this.localToGlobal(new Point(0, 0)).y;
			var bottom:Number = this.stage.stageHeight - this.localToGlobal(new Point(0, this.height)).y;
			
			if (isNaN(this._listWidth))
			{
				this.itemList.width = this.width;
			}
			
			if (isNaN(this._listHeight))
			{
				this.itemList.height = (maxListHeight < top && maxListHeight < bottom) ? maxListHeight : Math.max(top, bottom) / 2;
			}
			
			var listParent:DisplayObjectContainer = (this.listContainer == null) ? this.parent : this.listContainer;
			listParent.addChild(this.itemList);
			
			var listPosition:Point = listParent.globalToLocal(this.localToGlobal(new Point(0, 0)));
			this.itemList.x = Math.min(Math.max(0, listPosition.x - (this.itemList.width - this.width) / 2), this.stage.stageWidth - this.itemList.width);
			this.itemList.y = (forceBottom || top < bottom) ? listPosition.y + this.height : listPosition.y - this.itemList.height;
			
			this.stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown, false, 0, true);
			
			this.dispatchEvent(new Event(Event.OPEN));
		}
		
		/**
		 * 关闭列表
		 */
		private function closeList():void
		{
			if (this.stage != null)
			{
				this.stage.removeEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
			}
			
			this.itemList.remove();
			this.dispatchEvent(new Event(Event.CLOSE));
		}
		
		// -------------------------------------------------------------------------------------------------------- 函数
		
		override protected function init():void
		{
			super.init();
			
			this.registerEventListeners();
		}
		
		override protected function exit():void
		{
			super.exit();
			
			if (this.stage != null)
			{
				this.stage.removeEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
			}
			this.removeEventListeners();
		}
		
		/**
		 * 列表选择时
		 * @param event
		 */
		protected function onSelect(event:Event):void
		{
			this.closeList();
			
			this.selected = this.itemList.selected;
		}
		
		/**
		 * 鼠标点击时
		 * @param event
		 */
		protected function onClick(event:MouseEvent):void
		{
			if (this.itemList.parent == null)
			{
				this.openList();
			}
			else
			{
				this.closeList();
			}
		}
		
		/**
		 * 注册事件侦听
		 */
		private function registerEventListeners():void
		{
			this.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
			this.itemList.addEventListener(Event.SELECT, onSelect, false, 0, true);
		}
		
		/**
		 * 移除事件侦听
		 */
		private function removeEventListeners():void
		{
			this.removeEventListener(MouseEvent.CLICK, onClick);
			this.itemList.removeEventListener(Event.SELECT, onSelect);
		}
		
		/**
		 * 舞台鼠标按下时
		 * @param event
		 */
		private function onStageMouseDown(event:MouseEvent):void
		{
			var array:Array = this.stage.getObjectsUnderPoint(new Point(this.stage.mouseX, this.stage.mouseY));
			
			if (array.indexOf(this.itemList) < 0 && array.indexOf(this.listBackground) < 0 && array.indexOf(this) < 0)
			{
				this.closeList();
			}
		}
	
	}
}
